package main

import (
	"flag"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"path"
	"path/filepath"
	"strconv"
    "strings"
	"github.com/sevlyar/go-daemon"
)

//DEFAULTSERVICEPORT default service port
const DEFAULTSERVICEPORT = 7788

var port int = DEFAULTSERVICEPORT
var dae int = 0
var usessh int = 0
// var crt string = "./certs/server.crt"
// var key string = "./certs/server.key"
var crt string = "/root/Study/studybaseprojects/httpwebroot/certs/server.pem"
var key string = "/root/Study/studybaseprojects/httpwebroot/certs/server.key.pem"
var fav string = "/favicon.ico"
var webroot  string = "/home/dtryl/Study/studybaseprojects/httpwebroot"
var mediaroot  string = "/opt/testMediaFiles"

func redirect(w http.ResponseWriter, req *http.Request,newurl string) { 
  log.Println("redirect to:", newurl)
  w.Header().Set("Access-Control-Allow-Origin", "*")
  http.Redirect(w, req, newurl,
    // see @andreiavrammsd comment: often 307 > 301
  http.StatusTemporaryRedirect)
}


func servicehanderGetFile(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Access-Control-Allow-Origin", "*")
	r.ParseForm() //解析参数，默认是不会解析的
	log.Println("Recv:", r.URL.Path[1:len(r.URL.Path)])
    var urlpath=r.URL.Path[1:len(r.URL.Path)];
    if urlpath==""||urlpath=="/"{
        redirect(w,r,"index.html")  
        return
    }
	pwd, _ := os.Getwd()
	var des = pwd + string(os.PathSeparator) + urlpath
    
	paths, fileName := filepath.Split(des)
	log.Println(paths, fileName)    //获取路径中的目录及文件名 E:\data\  test.txt
	log.Println(filepath.Base(des)) //获取路径中的文件名test.txt
	log.Println(path.Ext(des))      //获取路径中的文件的后缀 .txt
    
	if fileName == "favicon.ico" || fileName == "vue.js"|| fileName == "frag_bunny.mp4"||strings.Contains(fileName, "jquery") {
		des = webroot+"/"+fileName
	}else if fileName=="/"{
        des= webroot+"/index.html"
    }else if path.Ext(des) == ".flv"|| path.Ext(des) == ".mp4" || path.Ext(des) == ".aac"|| path.Ext(des) == ".mp3"|| path.Ext(des) == ".wav"{
        des = mediaroot + "/" + fileName
    }
	//     log.Println("====",des)
	desStat, err := os.Stat(des)
	if err != nil {
		log.Println("File Not Exit", des)
		http.NotFoundHandler().ServeHTTP(w, r)
	} else if desStat.IsDir() {
		log.Println("File Is Dir", des)
		http.NotFoundHandler().ServeHTTP(w, r)
	} else {
		fileData, err := ioutil.ReadFile(des)
		if err != nil {
			log.Println("Read File Err:", err.Error())
		} else {
			log.Println("Send File:", des)

			if path.Ext(des) == ".css" {
				log.Println("set  mime-type:text/css")
				w.Header().Set("Content-Type", "text/css")
			}else if path.Ext(des) == ".html" {
                w.Header().Set("Content-Type", "text/html")
            }else if path.Ext(des) == ".js" {
                w.Header().Set("Content-Type", "application/javascript")
            }

			w.Write(fileData)
		}
	}
}
func servicehanderUpload(w http.ResponseWriter, r *http.Request)  {
    if r.Method != http.MethodPost {
        http.Error(w, "Only POST requests are allowed", http.StatusMethodNotAllowed)
        return
    }
 
    body, err := ioutil.ReadAll(r.Body)
    if err != nil {
        http.Error(w, "Error reading request body", http.StatusBadRequest)
        return
    }
    defer r.Body.Close()
 
    log.Printf("body from upload:%s",string(body))
 
    // 返回响应
    w.Write([]byte("POST request received"))
}
func servicehanderUploadAlarm(w http.ResponseWriter, r *http.Request)  {
    if r.Method != http.MethodPost {
        http.Error(w, "Only POST requests are allowed", http.StatusMethodNotAllowed)
        return
    }
 
    body, err := ioutil.ReadAll(r.Body)
    if err != nil {
        http.Error(w, "Error reading request body", http.StatusBadRequest)
        return
    }
    defer r.Body.Close()
 
    log.Printf("body from uploadalarm:%s",string(body))
 
    // 返回响应
    w.Write([]byte("POST request received"))
}
// To terminate the daemon use:
//  kill `cat sample.pid`
func main() {

	flag.IntVar(&port, "p", DEFAULTSERVICEPORT, "Set The Http Port")
	flag.IntVar(&dae, "d", 0, "Set Daemonize mode,default false")
	flag.IntVar(&usessh, "s", 0, "Use ssh mode,default false")
    
// 	pwd, _ := os.Getwd()
// 	var defaultcrtfilepath string = pwd + "/certs/server.crt"
// 	var defaultkeyfilepath string = pwd + "/certs/server.key"

  	var defaultcrtfilepath string = "/root/Study/studybaseprojects/httpwebroot/certs/server.pem"
	var defaultkeyfilepath string = "/root/Study/studybaseprojects/httpwebroot/certs/server.key.pem"
    
    
	flag.StringVar(&crt, "c", defaultcrtfilepath, "Set CRT file")
	flag.StringVar(&key, "k", defaultkeyfilepath, "Set CRT key file")
    flag.StringVar(&webroot, "r", "/root/Study/studybaseprojects/httpwebroot", "Set extra default web root path")
	flag.Parse()
	log.Println("port 	|dae 	|usessh 	|crt 								|key 							|webroot")
	log.Println(port, dae, usessh, crt, key, webroot)

	if 0 != dae {
		pidFile := os.Args[0] + ".pid"
		logFile := os.Args[0] + ".log"
		path, _ := filepath.Abs(filepath.Dir(os.Args[0]))
		cntxt := &daemon.Context{
			PidFileName: pidFile,
			PidFilePerm: 0644,
			LogFileName: logFile,
			LogFilePerm: 0640,
			WorkDir:     path,
			Umask:       027,
			Args:        os.Args,
		}

		d, err := cntxt.Reborn()
		if err != nil {
			log.Fatal("Unable to run: ", err)
		}
		if d != nil {
			return
		}
		defer cntxt.Release()
	}

	log.Println("- - - - - - - - - - - - - - -")
	log.Println("daemon started")

	serveHTTP(usessh, crt, key, port)
}

func serveHTTP(usessh int, crt string, key string, port int) {

	log.Printf("usessh:%d,crt:%s,key:%s,port:%d", usessh, crt, key, port)
	pwd, _ := os.Getwd()
	log.Printf("Listen On Port:%d pwd:%s\n", port, pwd)

	http.HandleFunc("/", servicehanderGetFile)
    http.HandleFunc("/upload", servicehanderUpload)
    http.HandleFunc("/uploadalarm", servicehanderUploadAlarm)
	if 0 != usessh {
		log.Println("Use https service,crt:%s,key:%s,port:%d", crt, key, port)
		err := http.ListenAndServeTLS(":"+strconv.Itoa(port), crt, key, nil)
		if nil != err {
			log.Fatalln("ListenAndServeTLS Err", err.Error())
		}
	} else {
		log.Printf("Use http service,port:%d", port)
		err := http.ListenAndServe(":"+strconv.Itoa(port), nil)
		if nil != err {
			log.Fatalln("ListenAndServe Err", err.Error())
		}
	}

}

